package com.ddstation.crm.organization_structure.util;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;


/**
 * @author DevinLiu 通用excel导入数据库
 */
@Component
public class ExcelUtil {

    private final static String excel2003L = ".xls"; // 2003- 版本的excel
    private final static String excel2007U = ".xlsx"; // 2007+ 版本的excel
    
    public static ExcelUtil excelUtil;  

    @PostConstruct
    public void init() {      
        excelUtil = this;  
    }   
    /**
     * 获取实体对象返回属性名称
     * 
     * @param obj 实体对象
     * @return
     * @throws Exception
     */
    private static java.lang.reflect.Field[] findEntityAllTypeName(Object obj) throws Exception {

        Class<? extends Object> cls = obj.getClass();

        return cls.getDeclaredFields();
    }

    /**
     * 根据文件选择excel版本
     * 
     * @return
     * @throws Exception
     */
    private static Workbook chooseWorkbook(MultipartFile file) throws Exception {
        Workbook workbook = null;
        // 获取文件名
        String oriName = file.getOriginalFilename();

        // 把MultipartFile转化为File
        File dfile = null;
        File fo = null;
        try {
            dfile = File.createTempFile("prefix", "_" + file.getOriginalFilename());
            file.transferTo(dfile);
            fo = dfile;
        } catch (IOException e) {
            e.printStackTrace();
        }
        String filename = file.getOriginalFilename();
        String fileType = (filename.substring(filename.lastIndexOf("."), filename.length())).toLowerCase();

        if (excel2003L.equals(fileType)) {
            workbook = new HSSFWorkbook(FileUtils.openInputStream(fo)); // 2003-
        } else if (excel2007U.equals(fileType)) {
            workbook = new XSSFWorkbook(FileUtils.openInputStream(fo)); // 2007+
        } else {
            throw new Exception("解析的文件格式有误！");
        }
        return workbook;
    }

    /**
     * 公共的导入excel方法
     * 
     * @param file      文件
     * @param sheetAt 工作簿下标
     * @param obj       实体类
     * @param fields    字段名列表
     * @return
     * @throws IOException
     */
    public static List<Object> importBaseExcel(MultipartFile file, int sheetAt, Object obj,List<String> fields) throws IOException {

        Workbook workbook = null;

        try {
            // 读取文件内容
            workbook = chooseWorkbook(file);

            // 获取工作表
            Sheet sheet = workbook.getSheetAt(sheetAt);

            // 获取sheet中第一行行号
            int firstRowNum = sheet.getFirstRowNum();
            // 获取sheet中最后一行行号
            int lastRowNum = sheet.getLastRowNum();

            // 获取该实体所有定义的属性 返回Field数组
            java.lang.reflect.Field[] entityName = findEntityAllTypeName(obj);

            String classname = obj.getClass().getName();
            Class<?> clazz = Class.forName(classname);

            List<Object> list = new ArrayList<Object>();

            // 循环插入数据
            for (int i = firstRowNum + 1; i <= lastRowNum; i++) {

                Row row = sheet.getRow(i);

                // 可以根据该类名生成Java对象
                Object pojo = clazz.newInstance();

                // 除自增编号外，实体字段匹配sheet列
                for (int j = 0; j < fields.size(); j++) {
                    String type = null;
                    Method m = null;
                    for(int k = 0; k < entityName.length; k++) {
                        if(fields.get(j) != null && fields.get(j).equalsIgnoreCase(entityName[k].getName())) {
                         // 获取属性的名字,将属性的首字符大写，方便构造set方法
                            String name = "set" + entityName[k].getName().substring(0, 1).toUpperCase()
                                    .concat(entityName[k].getName().substring(1)) + "";
                            // 获取属性的类型
                            type = entityName[k].getGenericType().toString();

                            // getMethod只能调用public声明的方法，而getDeclaredMethod基本可以调用任何类型声明的方法
                            m = obj.getClass().getDeclaredMethod(name, entityName[k].getType());
                            break;
                        }
                    }
                    if(type == null) {
                        continue;
                    }
                    Cell pname = row.getCell(j);
                    // 根据属性类型装入值
                    Object val = getVal(pname);
//                    if(fields.get(j).equalsIgnoreCase("partnerid")) {
//                        Query query = new Query();
//                        query.put("partnername", val);
//                        List<PartnerDO> partnerList = excelUtil.partnerService.list(query);
//                        if(partnerList != null && partnerList.size() > 0) {
//                            val = partnerList.get(0).getId() + "";
//                        }else {
//                            val = "0";
//                        }
//                    }
                    
                    switch (type) {
                    case "char":
                    case "java.lang.Character":
                    case "class java.lang.String":
                        m.invoke(pojo, val);
                        break;
                    case "int":
                    case "class java.lang.Integer":
                        if("".equals(val)) {
                            val = "0";
                        }
                        m.invoke(pojo, Integer.parseInt(val+""));
                        break;
                    case "class java.util.Date":
                        m.invoke(pojo, val);
                        break;
                    case "float":
                    case "double":
                    case "java.lang.Double":
                    case "java.lang.Float":
                    case "java.lang.Long":
                    case "java.lang.Short":
                    case "java.math.BigDecimal":
                        if("".equals(val)) {
                            val = "0";
                        }
                        m.invoke(pojo, Double.valueOf(val+""));
                        break;
                    default:
                        break;
                    }
                }
                list.add(pojo);
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            workbook.close();;
            //((OutputStream) workbook).close();
        }
    }

    /**
     * 处理类型
     * 
     * @param cell
     * @return
     */
    private static Object getVal(Cell cell) {
        if (null != cell) {
            switch (cell.getCellType()) {
            case XSSFCell.CELL_TYPE_NUMERIC: // 数字
                String val = cell.getNumericCellValue() + "";
                int index = val.indexOf(".");
                if (Integer.valueOf(val.substring(index + 1)) == 0) {
                    DecimalFormat df = new DecimalFormat("0");// 处理科学计数法
                    return df.format(cell.getNumericCellValue());
                }
                return cell.getNumericCellValue() + "";// double
            case XSSFCell.CELL_TYPE_STRING: // 字符串
                return cell.getStringCellValue() + "";
            case XSSFCell.CELL_TYPE_BOOLEAN: // Boolean
                return cell.getBooleanCellValue() + "";
            case XSSFCell.CELL_TYPE_FORMULA: // 公式
                try {
                    if (HSSFDateUtil.isCellDateFormatted(cell)) {
                        Date date = cell.getDateCellValue();
                        return date;
                    } else {
                        return String.valueOf((int) cell.getNumericCellValue());
                    }
                } catch (IllegalStateException e) {
                    return String.valueOf(cell.getRichStringCellValue());
                }
            case XSSFCell.CELL_TYPE_BLANK: // 空值
                return "";
            case XSSFCell.CELL_TYPE_ERROR: // 故障
                return "";
            default:
                return "未知类型   ";
            }
        } else {
            return "";
        }
    }

    /**
	 * <p>
	 * 导出带有头部标题行的Excel <br>
	 * 时间格式默认：yyyy-MM-dd hh:mm:ss <br>
	 * </p>
	 * 
	 * @param title 表格标题
	 * @param headers 头部标题集合
	 * @param dataset 数据集合
	 * @param out 输出流
	 * @param version 2003 或者 2007，不传时默认生成2003版本
	 */
	public static void exportExcel(String title,String[] headers, List<List<Object>> dataset, OutputStream out,String version) {
		if(StringUtils.isBlank(version) || excel2003L.equals(version.trim())){
//			exportExcel2003(title, headers, dataset, out, "yyyy-MM-dd HH:mm:ss");
		}else{
			exportExcel2007(title, headers, dataset, out, "yyyy-MM-dd HH:mm:ss");
		}
	}
	/**
	 * @param title
	 *            表格标题名
	 * @param headers
	 *            表格头部标题集合
	 * @param dataset
	 *            数据集合
	 * @param out
	 *            与输出设备关联的流对象，可以将EXCEL文档导出到本地文件或者网络中
	 * @param pattern
	 *            如果有时间数据，设定输出格式。默认为"yyyy-MM-dd hh:mm:ss"
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private static void exportExcel2007(String title, String[] headers,  List<List<Object>> dataset, OutputStream out, String pattern) {
		// 声明一个工作薄
		XSSFWorkbook workbook = new XSSFWorkbook();
		// 生成一个表格
		XSSFSheet sheet = workbook.createSheet(title);
		// 设置表格默认列宽度为15个字节
		sheet.setDefaultColumnWidth(20);
 
		// 产生表格标题行
		XSSFRow row = sheet.createRow(0);
		XSSFCell cellHeader;
		for (int i = 0; i < headers.length; i++) {
			cellHeader = row.createCell(i);
			cellHeader.setCellValue(new XSSFRichTextString(headers[i]));
		}
		// 遍历集合数据，产生数据行
		XSSFCell cell;
		//单元格的值
		Object value;
		for(int i = 0; i < dataset.size(); i++ ) {
			// 创建行
			row = sheet.createRow(i+1);
			for(int j = 0; j < dataset.get(i).size(); j++) {
				// 创建列
				cell = row.createCell(j);
				value = dataset.get(i).get(j);
				cell.setCellValue(value == null?null:value.toString());
			}
		}
		try {
			workbook.write(out);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
            e.printStackTrace();
        }finally {
			try {
				out.flush();
				out.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}